home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 July: Mac OS SDK / Dev.CD Jul 00 SDK2.toast / Development Kits / Hardware / Mac OS USB DDK / Mac OS USB DDK 1.4.1 / USB Software Locator Kit / SampleDriverInstallerExample / SampleShim.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-04-25  |  7.1 KB  |  254 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        SampleShim.c
  3.  
  4.  
  5.     Version:    1.1
  6.  
  7.     Copyright:    © 1998-1999 by Apple Computer, Inc., all rights reserved.
  8.  
  9. */
  10.  
  11. /*
  12. MacOS Headers
  13. */
  14. #include <CodeFragments.h>
  15. #include <Devices.h>
  16. #include <DriverServices.h>
  17. #include <MacTypes.h>
  18. #include <Processes.h>
  19. #include <Resources.h>
  20. #include <String.h>
  21. #include <TextUtils.h>
  22. #include <Errors.h>
  23. #include <Memory.h>
  24. #include <USB.h>
  25.  
  26. /*
  27. Driver Headers
  28. */
  29. #include "SampleDriverVersion.h"
  30. #include "SampleShim.h"
  31.  
  32. #define kUSBInterfaceType        'usbi'
  33. #define kUSBDeviceType            'usbd'
  34. #define kDispatchTableAddress    "DispatchTableAddr"
  35.  
  36. /*
  37. Global variables used by the Shim
  38. */
  39. static Boolean                 shimInFile;
  40. static FSSpec                shimFSSpec;
  41. static TimerID                gGiveTimeTimer = nil;
  42. static DriverRefNum            gNewDrvrRef = 0;
  43. static USBDeviceNotificationParameterBlock     gpb;
  44. static Boolean                gNotifierInstalledFlag = false;
  45.  
  46.  
  47. OSErr CFragInitRoutine(CFragInitBlockPtr initBlkPtr);
  48. OSStatus USBShim(void);
  49. OSStatus FindMatchingRegEntryForUSBRef (USBDeviceRef ref, ResType theType, RegEntryID *resultID);
  50.  
  51.  
  52. /*
  53. Exported Functions for the Code Fragment Manager
  54. */
  55. // This routine gets called by the Code Fragment Manager when the shim's code fragment is loaded
  56. OSErr CFragInitRoutine(CFragInitBlockPtr initBlkPtr)
  57. {
  58.     shimInFile = false;
  59.     
  60.     if (CFragHasFileLocation(initBlkPtr->fragLocator.where))
  61.     {
  62.         shimInFile = true;
  63.         shimFSSpec = *(initBlkPtr->fragLocator.u.onDisk.fileSpec);            // save the FSSpec, in case we need it later
  64.     }
  65.     return noErr;
  66. }
  67.  
  68.  
  69. /*
  70. Functions Exported for the USB Expert
  71. */
  72. // This routine is exported for use by the USB Expert to initialize the shim when
  73. // the expert loads it
  74. OSStatus USBShim(void)
  75. {
  76.     OSStatus status = noErr;
  77.  
  78.     // Setup notification for Vendor Specific Devices
  79.     gpb.usbDeviceNotification     = kNotifyAnyEvent;            // tell me about everything
  80.     gpb.usbClass                 = kUSBAnyClass;
  81.     gpb.usbSubClass             = kUSBAnySubClass;
  82.     gpb.usbProtocol             = kUSBAnyProtocol;
  83.     gpb.usbVendor                 = 0x0547;            // Notify me of my specific Vendor ID
  84.     gpb.usbProduct                 = 0x1002;            // Notify me of my specific Product ID
  85.     gpb.result = noErr;
  86.     gpb.callback = (USBDeviceNotificationCallbackProcPtr) &myNotificationCallback;        
  87.     gpb.refcon = nil;
  88.      USBInstallDeviceNotification (&gpb);
  89.      gNotifierInstalledFlag = true;        // keep track of whether notifier routine was installed    
  90.  
  91.     return status;
  92. }
  93.  
  94. // This routine is exported for use by the USB Expert to terminate the shim before it gets removed
  95. void USBShimTermination(void)
  96. {
  97.     // check if notifier was installed
  98.     if (gNotifierInstalledFlag == true)
  99.     {
  100.         // Remove the device notofication
  101.         USBRemoveDeviceNotification(gpb.token); 
  102.     }
  103. }
  104.  
  105. // This function is passed to the USB Expert for device add/remove notification
  106. void myNotificationCallback(USBDeviceNotificationParameterBlock *pb)
  107. {
  108.     CFragConnectionID    connID;
  109.     CFragSymbolClass    symClass;
  110.     RegEntryID            regEntry;
  111.     OSStatus            err;
  112.     THz                    saveZone;
  113.     Ptr                    dispatchArrayPtr;
  114.             
  115.     
  116.     switch(pb->usbDeviceNotification)        // why were we notified?
  117.     {
  118.         case kNotifyAddDevice:                // because mass storage device appeared
  119.         case kNotifyAddInterface:            // because mass storage interface appeared
  120.         {
  121.             USBExpertStatus(pb->usbDeviceRef, "\pdevice/interface added", 0);
  122.                 // the device or interface attachment has been detected
  123.                 // first find the CFragConnectionID associated with this USBDeviceRef
  124.             err = USBGetDriverConnectionID(&pb->usbDeviceRef, &connID);
  125.             if (err == noErr)
  126.             {
  127.                     // find the matching RegEntryID for the device
  128.                 err = FindMatchingRegEntryForUSBRef(pb->usbDeviceRef, kUSBDeviceType, ®Entry);
  129.                 if (err == noErr)
  130.                 {
  131.                     
  132.                     saveZone = GetZone();    // save the current zone
  133.                     SetZone(SystemZone());    // set the current zone to the System zone
  134.                             // otherwise the FindSymbol call will fail to find the dispatch table symbol
  135.                     
  136.                     USBExpertStatus(pb->usbDeviceRef, "\pDevice found", 0);
  137.                     
  138.                     SetZone(saveZone);
  139.  
  140.                 }
  141.                 else
  142.                 {
  143.                     USBExpertStatus(pb->usbDeviceRef, "\pmyNotificationCallback: error calling FindMatchingRegEntryForUSBRef", err);
  144.                 }
  145.             }
  146.             else
  147.             {
  148.                 USBExpertStatus(pb->usbDeviceRef, "\pmyNotificationCallback: error calling USBGetDriverConnectionID", err);
  149.             }
  150.         }
  151.         break;
  152.             
  153.         case kNotifyRemoveDevice:            // because a mass storage device or interface disappeared
  154.         case kNotifyRemoveInterface:        // because a mass storage device or interface disappeared
  155.         {
  156.             USBExpertStatus(pb->usbDeviceRef, "\pdevice/interface removed", 0);
  157.         }
  158.         break;
  159.             
  160.         default:
  161.             break;
  162.     }
  163. }
  164.  
  165. /*
  166. OSStatus FindMatchingRegEntryForUSBRef (USBDeviceRef ref, ResType theType, RegEntryID *theEntry)
  167.     takes the USBDeviceRef and searches the name registry for the registered entry based on theType
  168.     If the USBDeviceRef is found, then the corresponding RegEntryID is returned.
  169.     for theType parameter pass in 'usbd' for a USB Device or
  170.                                   'usbi' for a USB Interface 
  171.  
  172. */
  173. OSStatus FindMatchingRegEntryForUSBRef (USBDeviceRef ref, ResType theType, RegEntryID *theEntry)
  174. {
  175.     OSStatus                err = noErr;
  176.     OSStatus                status;
  177.     RegEntryIter            cookie;
  178.     unsigned char              usbNodeStr[32] = "\pAAPL,USBNodeType";
  179.     RegCStrEntryNamePtr     usbNodeCStr = p2cstr(usbNodeStr);
  180.     unsigned char              usbInterfaceRefStr[32] = "\pinterfaceRef";
  181.     unsigned char            usbDeviceRefStr[32] = "\pdeviceRef";
  182.     RegCStrEntryNamePtr     usbRefCStr;
  183.     RegEntryIterationOp     iterOp;
  184.     ResType                    usbNodeType;
  185.     RegPropertyValueSize    theSize;
  186.     USBDeviceRef            tempRef;
  187.     Boolean                 done = false;
  188.     Boolean                    found = false;
  189.     
  190.     if ((theType != kUSBInterfaceType) && (theType != kUSBDeviceType))
  191.         return -1;    // if the desired type is not 'usbd' nor 'usbi' then return a generic error
  192.         
  193.     err = RegistryEntryIDInit( theEntry );
  194.     if (err != noErr)
  195.     {
  196.         USBExpertStatus(ref, "\pFindMatchingRegEntryForUSBRef: RegistryEntryIDInit failed", err);
  197.         return err;
  198.     }
  199.  
  200.     err = RegistryEntryIterateCreate( &cookie );
  201.     if (err != noErr)
  202.     {
  203.         USBExpertStatus(ref, "\pFindMatchingRegEntryForUSBRef: RegistryEntryIterateCreate failed", err);
  204.         return err;
  205.     }
  206.  
  207.     iterOp = kRegIterDescendants;
  208.  
  209.     err = RegistryEntrySearch( &cookie, iterOp, theEntry, &done,
  210.                                                        usbNodeCStr, nil, 0);
  211.  
  212.         // set up the usbRefCStr so that we will search for either the interfaceRef or deviceRef
  213.         // property
  214.     if (theType == kUSBInterfaceType)
  215.         usbRefCStr = p2cstr( usbInterfaceRefStr);
  216.     else if (theType == kUSBDeviceType)
  217.         usbRefCStr = p2cstr( usbDeviceRefStr);
  218.     
  219.     while ((err == noErr) && (done == false))
  220.     {
  221.         theSize = sizeof(usbNodeType);
  222.         err = RegistryPropertyGet(theEntry, usbNodeCStr, &usbNodeType, &theSize );
  223.         if (err == noErr)
  224.         {
  225.             if (usbNodeType == theType)
  226.             {
  227.                 theSize = sizeof(USBDeviceRef);
  228.                     
  229.                 err = RegistryPropertyGet(theEntry, usbRefCStr, &tempRef, &theSize);
  230.                 if ((err == noErr) && tempRef == ref)
  231.                 {
  232.                     found = true;
  233.                     break;
  234.                 }
  235.             }
  236.             
  237.             err = RegistryEntrySearch( &cookie, iterOp, theEntry, &done, usbNodeCStr, nil, 0);
  238.         }
  239.         else
  240.             USBExpertStatus(ref, "\pFindMatchingRegEntryForUSBRef: error calling RegistryPropertyGet", err);
  241.         
  242.      
  243.     }
  244.  
  245.     RegistryEntryIterateDispose( &cookie );
  246.  
  247.     if (found == false)
  248.         err = nrNotFoundErr;
  249.         
  250.     return err;
  251.  
  252. }
  253.  
  254.